/**
 * 有序列表,无序列表插件
 * @file
 * @since 1.2.6.1
 */

UE.plugins["list"] = function() {
  var me = this,
    notExchange = {
      TD: 1,
      PRE: 1,
      BLOCKQUOTE: 1
    };
  var customStyle = {
    cn: "cn-1-",
    cn1: "cn-2-",
    cn2: "cn-3-",
    num: "num-1-",
    num1: "num-2-",
    num2: "num-3-",
    dash: "dash",
    dot: "dot"
  };

  me.setOpt({
    autoTransWordToList: false,
    insertorderedlist: {
      num: "",
      num1: "",
      num2: "",
      cn: "",
      cn1: "",
      cn2: "",
      decimal: "",
      "lower-alpha": "",
      "lower-roman": "",
      "upper-alpha": "",
      "upper-roman": ""
    },
    insertunorderedlist: {
      circle: "",
      disc: "",
      square: "",
      dash: "",
      dot: ""
    },
    listDefaultPaddingLeft: "30",
    listiconpath: me.options.UEDITOR_HOME_URL + "themes/ueditor-list/",
    maxListLevel: -1, //-1不限制
    disablePInList: false
  });
  function listToArray(list) {
    var arr = [];
    for (var p in list) {
      arr.push(p);
    }
    return arr;
  }
  var listStyle = {
    OL: listToArray(me.options.insertorderedlist),
    UL: listToArray(me.options.insertunorderedlist)
  };
  var liiconpath = me.options.listiconpath;

  //根据用户配置，调整customStyle
  for (var s in customStyle) {
    if (
      !me.options.insertorderedlist.hasOwnProperty(s) &&
      !me.options.insertunorderedlist.hasOwnProperty(s)
    ) {
      delete customStyle[s];
    }
  }

  me.ready(function() {
    var customCss = [];
    for (var p in customStyle) {
      if (p == "dash" || p == "dot") {
        customCss.push(
          "li.list-" +
            customStyle[p] +
            "{background-image:url(" +
            liiconpath +
            customStyle[p] +
            ".gif)}"
        );
        customCss.push(
          "ul.custom_" +
            p +
            "{list-style:none;}ul.custom_" +
            p +
            " li{background-position:0 3px;background-repeat:no-repeat}"
        );
      } else {
        for (var i = 0; i < 99; i++) {
          customCss.push(
            "li.list-" +
              customStyle[p] +
              i +
              "{background-image:url(" +
              liiconpath +
              "list-" +
              customStyle[p] +
              i +
              ".gif)}"
          );
        }
        customCss.push(
          "ol.custom_" +
            p +
            "{list-style:none;}ol.custom_" +
            p +
            " li{background-position:0 3px;background-repeat:no-repeat}"
        );
      }
      switch (p) {
        case "cn":
          customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
          customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
          customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
          break;
        case "cn1":
          customCss.push("li.list-" + p + "-paddingleft-1{padding-left:30px}");
          customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
          customCss.push("li.list-" + p + "-paddingleft-3{padding-left:55px}");
          break;
        case "cn2":
          customCss.push("li.list-" + p + "-paddingleft-1{padding-left:40px}");
          customCss.push("li.list-" + p + "-paddingleft-2{padding-left:55px}");
          customCss.push("li.list-" + p + "-paddingleft-3{padding-left:68px}");
          break;
        case "num":
        case "num1":
          customCss.push("li.list-" + p + "-paddingleft-1{padding-left:25px}");
          break;
        case "num2":
          customCss.push("li.list-" + p + "-paddingleft-1{padding-left:35px}");
          customCss.push("li.list-" + p + "-paddingleft-2{padding-left:40px}");
          break;
        case "dash":
          customCss.push("li.list-" + p + "-paddingleft{padding-left:35px}");
          break;
        case "dot":
          customCss.push("li.list-" + p + "-paddingleft{padding-left:20px}");
      }
    }
    customCss.push(".list-paddingleft-1{padding-left:0}");
    customCss.push(
      ".list-paddingleft-2{padding-left:" +
        me.options.listDefaultPaddingLeft +
        "px}"
    );
    customCss.push(
      ".list-paddingleft-3{padding-left:" +
        me.options.listDefaultPaddingLeft * 2 +
        "px}"
    );
    //如果不给宽度会在自定应样式里出现滚动条
    utils.cssRule(
      "list",
      "ol,ul{margin:0;pading:0;" +
        (browser.ie ? "" : "width:95%") +
        "}li{clear:both;}" +
        customCss.join("\n"),
      me.document
    );
  });
  //单独处理剪切的问题
  me.ready(function() {
    domUtils.on(me.body, "cut", function() {
      setTimeout(function() {
        var rng = me.selection.getRange(),
          li;
        //trace:3416
        if (!rng.collapsed) {
          if (
            (li = domUtils.findParentByTagName(rng.startContainer, "li", true))
          ) {
            if (!li.nextSibling && domUtils.isEmptyBlock(li)) {
              var pn = li.parentNode,
                node;
              if ((node = pn.previousSibling)) {
                domUtils.remove(pn);
                rng.setStartAtLast(node).collapse(true);
                rng.select(true);
              } else if ((node = pn.nextSibling)) {
                domUtils.remove(pn);
                rng.setStartAtFirst(node).collapse(true);
                rng.select(true);
              } else {
                var tmpNode = me.document.createElement("p");
                domUtils.fillNode(me.document, tmpNode);
                pn.parentNode.insertBefore(tmpNode, pn);
                domUtils.remove(pn);
                rng.setStart(tmpNode, 0).collapse(true);
                rng.select(true);
              }
            }
          }
        }
      });
    });
  });

  function getStyle(node) {
    var cls = node.className;
    if (domUtils.hasClass(node, /custom_/)) {
      return cls.match(/custom_(\w+)/)[1];
    }
    return domUtils.getStyle(node, "list-style-type");
  }

  me.addListener("beforepaste", function(type, html) {
    var me = this,
      rng = me.selection.getRange(),
      li;
    var root = UE.htmlparser(html.html, true);
    if ((li = domUtils.findParentByTagName(rng.startContainer, "li", true))) {
      var list = li.parentNode,
        tagName = list.tagName == "OL" ? "ul" : "ol";
      utils.each(root.getNodesByTagName(tagName), function(n) {
        n.tagName = list.tagName;
        n.setAttr();
        if (n.parentNode === root) {
          type = getStyle(list) || (list.tagName == "OL" ? "decimal" : "disc");
        } else {
          var className = n.parentNode.getAttr("class");
          if (className && /custom_/.test(className)) {
            type = className.match(/custom_(\w+)/)[1];
          } else {
            type = n.parentNode.getStyle("list-style-type");
          }
          if (!type) {
            type = list.tagName == "OL" ? "decimal" : "disc";
          }
        }
        var index = utils.indexOf(listStyle[list.tagName], type);
        if (n.parentNode !== root)
          index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
        var currentStyle = listStyle[list.tagName][index];
        if (customStyle[currentStyle]) {
          n.setAttr("class", "custom_" + currentStyle);
        } else {
          n.setStyle("list-style-type", currentStyle);
        }
      });
    }

    html.html = root.toHtml();
  });
  //导出时，去掉p标签
  me.getOpt("disablePInList") === true &&
    me.addOutputRule(function(root) {
      utils.each(root.getNodesByTagName("li"), function(li) {
        var newChildrens = [],
          index = 0;
        utils.each(li.children, function(n) {
          if (n.tagName == "p") {
            var tmpNode;
            while ((tmpNode = n.children.pop())) {
              newChildrens.splice(index, 0, tmpNode);
              tmpNode.parentNode = li;
              lastNode = tmpNode;
            }
            tmpNode = newChildrens[newChildrens.length - 1];
            if (
              !tmpNode ||
              tmpNode.type != "element" ||
              tmpNode.tagName != "br"
            ) {
              var br = UE.uNode.createElement("br");
              br.parentNode = li;
              newChildrens.push(br);
            }

            index = newChildrens.length;
          }
        });
        if (newChildrens.length) {
          li.children = newChildrens;
        }
      });
    });
  //进入编辑器的li要套p标签
  me.addInputRule(function(root) {
    utils.each(root.getNodesByTagName("li"), function(li) {
      var tmpP = UE.uNode.createElement("p");
      for (var i = 0, ci; (ci = li.children[i]); ) {
        if (ci.type == "text" || dtd.p[ci.tagName]) {
          tmpP.appendChild(ci);
        } else {
          if (tmpP.firstChild()) {
            li.insertBefore(tmpP, ci);
            tmpP = UE.uNode.createElement("p");
            i = i + 2;
          } else {
            i++;
          }
        }
      }
      if ((tmpP.firstChild() && !tmpP.parentNode) || !li.firstChild()) {
        li.appendChild(tmpP);
      }
      //trace:3357
      //p不能为空
      if (!tmpP.firstChild()) {
        tmpP.innerHTML(browser.ie ? "&nbsp;" : "<br/>");
      }
      //去掉末尾的空白
      var p = li.firstChild();
      var lastChild = p.lastChild();
      if (
        lastChild &&
        lastChild.type == "text" &&
        /^\s*$/.test(lastChild.data)
      ) {
        p.removeChild(lastChild);
      }
    });
    if (me.options.autoTransWordToList) {
      var orderlisttype = {
        num1: /^\d+\)/,
        decimal: /^\d+\./,
        "lower-alpha": /^[a-z]+\)/,
        "upper-alpha": /^[A-Z]+\./,
        cn: /^[\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+[\u3001]/,
        cn2: /^\([\u4E00\u4E8C\u4E09\u56DB\u516d\u4e94\u4e03\u516b\u4e5d]+\)/
      },
        unorderlisttype = {
          square: "n"
        };
      function checkListType(content, container) {
        var span = container.firstChild();
        if (
          span &&
          span.type == "element" &&
          span.tagName == "span" &&
          /Wingdings|Symbol/.test(span.getStyle("font-family"))
        ) {
          for (var p in unorderlisttype) {
            if (unorderlisttype[p] == span.data) {
              return p;
            }
          }
          return "disc";
        }
        for (var p in orderlisttype) {
          if (orderlisttype[p].test(content)) {
            return p;
          }
        }
      }
      utils.each(root.getNodesByTagName("p"), function(node) {
        if (node.getAttr("class") != "MsoListParagraph") {
          return;
        }

        //word粘贴过来的会带有margin要去掉,但这样也可能会误命中一些央视
        node.setStyle("margin", "");
        node.setStyle("margin-left", "");
        node.setAttr("class", "");

        function appendLi(list, p, type) {
          if (list.tagName == "ol") {
            if (browser.ie) {
              var first = p.firstChild();
              if (
                first.type == "element" &&
                first.tagName == "span" &&
                orderlisttype[type].test(first.innerText())
              ) {
                p.removeChild(first);
              }
            } else {
              p.innerHTML(p.innerHTML().replace(orderlisttype[type], ""));
            }
          } else {
            p.removeChild(p.firstChild());
          }

          var li = UE.uNode.createElement("li");
          li.appendChild(p);
          list.appendChild(li);
        }
        var tmp = node,
          type,
          cacheNode = node;

        if (
          node.parentNode.tagName != "li" &&
          (type = checkListType(node.innerText(), node))
        ) {
          var list = UE.uNode.createElement(
            me.options.insertorderedlist.hasOwnProperty(type) ? "ol" : "ul"
          );
          if (customStyle[type]) {
            list.setAttr("class", "custom_" + type);
          } else {
            list.setStyle("list-style-type", type);
          }
          while (
            node &&
            node.parentNode.tagName != "li" &&
            checkListType(node.innerText(), node)
          ) {
            tmp = node.nextSibling();
            if (!tmp) {
              node.parentNode.insertBefore(list, node);
            }
            appendLi(list, node, type);
            node = tmp;
          }
          if (!list.parentNode && node && node.parentNode) {
            node.parentNode.insertBefore(list, node);
          }
        }
        var span = cacheNode.firstChild();
        if (
          span &&
          span.type == "element" &&
          span.tagName == "span" &&
          /^\s*(&nbsp;)+\s*$/.test(span.innerText())
        ) {
          span.parentNode.removeChild(span);
        }
      });
    }
  });

  //调整索引标签
  me.addListener("contentchange", function() {
    adjustListStyle(me.document);
  });

  function adjustListStyle(doc, ignore) {
    utils.each(domUtils.getElementsByTagName(doc, "ol ul"), function(node) {
      if (!domUtils.inDoc(node, doc)) return;

      var parent = node.parentNode;
      if (parent.tagName == node.tagName) {
        var nodeStyleType =
          getStyle(node) || (node.tagName == "OL" ? "decimal" : "disc"),
          parentStyleType =
            getStyle(parent) || (parent.tagName == "OL" ? "decimal" : "disc");
        if (nodeStyleType == parentStyleType) {
          var styleIndex = utils.indexOf(
            listStyle[node.tagName],
            nodeStyleType
          );
          styleIndex = styleIndex + 1 == listStyle[node.tagName].length
            ? 0
            : styleIndex + 1;
          setListStyle(node, listStyle[node.tagName][styleIndex]);
        }
      }
      var index = 0,
        type = 2;
      if (domUtils.hasClass(node, /custom_/)) {
        if (
          !(
            /[ou]l/i.test(parent.tagName) &&
            domUtils.hasClass(parent, /custom_/)
          )
        ) {
          type = 1;
        }
      } else {
        if (
          /[ou]l/i.test(parent.tagName) &&
          domUtils.hasClass(parent, /custom_/)
        ) {
          type = 3;
        }
      }

      var style = domUtils.getStyle(node, "list-style-type");
      style && (node.style.cssText = "list-style-type:" + style);
      node.className =
        utils.trim(node.className.replace(/list-paddingleft-\w+/, "")) +
        " list-paddingleft-" +
        type;
      utils.each(domUtils.getElementsByTagName(node, "li"), function(li) {
        li.style.cssText && (li.style.cssText = "");
        if (!li.firstChild) {
          domUtils.remove(li);
          return;
        }
        if (li.parentNode !== node) {
          return;
        }
        index++;
        if (domUtils.hasClass(node, /custom_/)) {
          var paddingLeft = 1,
            currentStyle = getStyle(node);
          if (node.tagName == "OL") {
            if (currentStyle) {
              switch (currentStyle) {
                case "cn":
                case "cn1":
                case "cn2":
                  if (
                    index > 10 &&
                    (index % 10 == 0 || (index > 10 && index < 20))
                  ) {
                    paddingLeft = 2;
                  } else if (index > 20) {
                    paddingLeft = 3;
                  }
                  break;
                case "num2":
                  if (index > 9) {
                    paddingLeft = 2;
                  }
              }
            }
            li.className =
              "list-" +
              customStyle[currentStyle] +
              index +
              " " +
              "list-" +
              currentStyle +
              "-paddingleft-" +
              paddingLeft;
          } else {
            li.className =
              "list-" +
              customStyle[currentStyle] +
              " " +
              "list-" +
              currentStyle +
              "-paddingleft";
          }
        } else {
          li.className = li.className.replace(/list-[\w\-]+/gi, "");
        }
        var className = li.getAttribute("class");
        if (className !== null && !className.replace(/\s/g, "")) {
          domUtils.removeAttributes(li, "class");
        }
      });
      !ignore &&
        adjustList(
          node,
          node.tagName.toLowerCase(),
          getStyle(node) || domUtils.getStyle(node, "list-style-type"),
          true
        );
    });
  }
  function adjustList(list, tag, style, ignoreEmpty) {
    var nextList = list.nextSibling;
    if (
      nextList &&
      nextList.nodeType == 1 &&
      nextList.tagName.toLowerCase() == tag &&
      (getStyle(nextList) ||
        domUtils.getStyle(nextList, "list-style-type") ||
        (tag == "ol" ? "decimal" : "disc")) == style
    ) {
      domUtils.moveChild(nextList, list);
      if (nextList.childNodes.length == 0) {
        domUtils.remove(nextList);
      }
    }
    if (nextList && domUtils.isFillChar(nextList)) {
      domUtils.remove(nextList);
    }
    var preList = list.previousSibling;
    if (
      preList &&
      preList.nodeType == 1 &&
      preList.tagName.toLowerCase() == tag &&
      (getStyle(preList) ||
        domUtils.getStyle(preList, "list-style-type") ||
        (tag == "ol" ? "decimal" : "disc")) == style
    ) {
      domUtils.moveChild(list, preList);
    }
    if (preList && domUtils.isFillChar(preList)) {
      domUtils.remove(preList);
    }
    !ignoreEmpty && domUtils.isEmptyBlock(list) && domUtils.remove(list);
    if (getStyle(list)) {
      adjustListStyle(list.ownerDocument, true);
    }
  }

  function setListStyle(list, style) {
    if (customStyle[style]) {
      list.className = "custom_" + style;
    }
    try {
      domUtils.setStyle(list, "list-style-type", style);
    } catch (e) {}
  }
  function clearEmptySibling(node) {
    var tmpNode = node.previousSibling;
    if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
      domUtils.remove(tmpNode);
    }
    tmpNode = node.nextSibling;
    if (tmpNode && domUtils.isEmptyBlock(tmpNode)) {
      domUtils.remove(tmpNode);
    }
  }

  me.addListener("keydown", function(type, evt) {
    function preventAndSave() {
      evt.preventDefault ? evt.preventDefault() : (evt.returnValue = false);
      me.fireEvent("contentchange");
      me.undoManger && me.undoManger.save();
    }
    function findList(node, filterFn) {
      while (node && !domUtils.isBody(node)) {
        if (filterFn(node)) {
          return null;
        }
        if (node.nodeType == 1 && /[ou]l/i.test(node.tagName)) {
          return node;
        }
        node = node.parentNode;
      }
      return null;
    }
    var keyCode = evt.keyCode || evt.which;
    if (keyCode == 13 && !evt.shiftKey) {
      //回车
      var rng = me.selection.getRange(),
        parent = domUtils.findParent(
          rng.startContainer,
          function(node) {
            return domUtils.isBlockElm(node);
          },
          true
        ),
        li = domUtils.findParentByTagName(rng.startContainer, "li", true);
      if (parent && parent.tagName != "PRE" && !li) {
        var html = parent.innerHTML.replace(
          new RegExp(domUtils.fillChar, "g"),
          ""
        );
        if (/^\s*1\s*\.[^\d]/.test(html)) {
          parent.innerHTML = html.replace(/^\s*1\s*\./, "");
          rng.setStartAtLast(parent).collapse(true).select();
          me.__hasEnterExecCommand = true;
          me.execCommand("insertorderedlist");
          me.__hasEnterExecCommand = false;
        }
      }
      var range = me.selection.getRange(),
        start = findList(range.startContainer, function(node) {
          return node.tagName == "TABLE";
        }),
        end = range.collapsed
          ? start
          : findList(range.endContainer, function(node) {
              return node.tagName == "TABLE";
            });

      if (start && end && start === end) {
        if (!range.collapsed) {
          start = domUtils.findParentByTagName(
            range.startContainer,
            "li",
            true
          );
          end = domUtils.findParentByTagName(range.endContainer, "li", true);
          if (start && end && start === end) {
            range.deleteContents();
            li = domUtils.findParentByTagName(range.startContainer, "li", true);
            if (li && domUtils.isEmptyBlock(li)) {
              pre = li.previousSibling;
              next = li.nextSibling;
              p = me.document.createElement("p");

              domUtils.fillNode(me.document, p);
              parentList = li.parentNode;
              if (pre && next) {
                range.setStart(next, 0).collapse(true).select(true);
                domUtils.remove(li);
              } else {
                if ((!pre && !next) || !pre) {
                  parentList.parentNode.insertBefore(p, parentList);
                } else {
                  li.parentNode.parentNode.insertBefore(
                    p,
                    parentList.nextSibling
                  );
                }
                domUtils.remove(li);
                if (!parentList.firstChild) {
                  domUtils.remove(parentList);
                }
                range.setStart(p, 0).setCursor();
              }
              preventAndSave();
              return;
            }
          } else {
            var tmpRange = range.cloneRange(),
              bk = tmpRange.collapse(false).createBookmark();

            range.deleteContents();
            tmpRange.moveToBookmark(bk);
            var li = domUtils.findParentByTagName(
              tmpRange.startContainer,
              "li",
              true
            );

            clearEmptySibling(li);
            tmpRange.select();
            preventAndSave();
            return;
          }
        }

        li = domUtils.findParentByTagName(range.startContainer, "li", true);

        if (li) {
          if (domUtils.isEmptyBlock(li)) {
            bk = range.createBookmark();
            var parentList = li.parentNode;
            if (li !== parentList.lastChild) {
              domUtils.breakParent(li, parentList);
              clearEmptySibling(li);
            } else {
              parentList.parentNode.insertBefore(li, parentList.nextSibling);
              if (domUtils.isEmptyNode(parentList)) {
                domUtils.remove(parentList);
              }
            }
            //嵌套不处理
            if (!dtd.$list[li.parentNode.tagName]) {
              if (!domUtils.isBlockElm(li.firstChild)) {
                p = me.document.createElement("p");
                li.parentNode.insertBefore(p, li);
                while (li.firstChild) {
                  p.appendChild(li.firstChild);
                }
                domUtils.remove(li);
              } else {
                domUtils.remove(li, true);
              }
            }
            range.moveToBookmark(bk).select();
          } else {
            var first = li.firstChild;
            if (!first || !domUtils.isBlockElm(first)) {
              var p = me.document.createElement("p");

              !li.firstChild && domUtils.fillNode(me.document, p);
              while (li.firstChild) {
                p.appendChild(li.firstChild);
              }
              li.appendChild(p);
              first = p;
            }

            var span = me.document.createElement("span");

            range.insertNode(span);
            domUtils.breakParent(span, li);

            var nextLi = span.nextSibling;
            first = nextLi.firstChild;

            if (!first) {
              p = me.document.createElement("p");

              domUtils.fillNode(me.document, p);
              nextLi.appendChild(p);
              first = p;
            }
            if (domUtils.isEmptyNode(first)) {
              first.innerHTML = "";
              domUtils.fillNode(me.document, first);
            }

            range.setStart(first, 0).collapse(true).shrinkBoundary().select();
            domUtils.remove(span);
            var pre = nextLi.previousSibling;
            if (pre && domUtils.isEmptyBlock(pre)) {
              pre.innerHTML = "<p></p>";
              domUtils.fillNode(me.document, pre.firstChild);
            }
          }
          //                        }
          preventAndSave();
        }
      }
    }
    if (keyCode == 8) {
      //修中ie中li下的问题
      range = me.selection.getRange();
      if (range.collapsed && domUtils.isStartInblock(range)) {
        tmpRange = range.cloneRange().trimBoundary();
        li = domUtils.findParentByTagName(range.startContainer, "li", true);
        //要在li的最左边，才能处理
        if (li && domUtils.isStartInblock(tmpRange)) {
          start = domUtils.findParentByTagName(range.startContainer, "p", true);
          if (start && start !== li.firstChild) {
            var parentList = domUtils.findParentByTagName(start, ["ol", "ul"]);
            domUtils.breakParent(start, parentList);
            clearEmptySibling(start);
            me.fireEvent("contentchange");
            range.setStart(start, 0).setCursor(false, true);
            me.fireEvent("saveScene");
            domUtils.preventDefault(evt);
            return;
          }

          if (li && (pre = li.previousSibling)) {
            if (keyCode == 46 && li.childNodes.length) {
              return;
            }
            //有可能上边的兄弟节点是个2级菜单，要追加到2级菜单的最后的li
            if (dtd.$list[pre.tagName]) {
              pre = pre.lastChild;
            }
            me.undoManger && me.undoManger.save();
            first = li.firstChild;
            if (domUtils.isBlockElm(first)) {
              if (domUtils.isEmptyNode(first)) {
                //                                    range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
                pre.appendChild(first);
                range.setStart(first, 0).setCursor(false, true);
                //first不是唯一的节点
                while (li.firstChild) {
                  pre.appendChild(li.firstChild);
                }
              } else {
                span = me.document.createElement("span");
                range.insertNode(span);
                //判断pre是否是空的节点,如果是<p><br/></p>类型的空节点，干掉p标签防止它占位
                if (domUtils.isEmptyBlock(pre)) {
                  pre.innerHTML = "";
                }
                domUtils.moveChild(li, pre);
                range.setStartBefore(span).collapse(true).select(true);

                domUtils.remove(span);
              }
            } else {
              if (domUtils.isEmptyNode(li)) {
                var p = me.document.createElement("p");
                pre.appendChild(p);
                range.setStart(p, 0).setCursor();
                //                                    range.setEnd(pre, pre.childNodes.length).shrinkBoundary().collapse().select(true);
              } else {
                range
                  .setEnd(pre, pre.childNodes.length)
                  .collapse()
                  .select(true);
                while (li.firstChild) {
                  pre.appendChild(li.firstChild);
                }
              }
            }
            domUtils.remove(li);
            me.fireEvent("contentchange");
            me.fireEvent("saveScene");
            domUtils.preventDefault(evt);
            return;
          }
          //trace:980

          if (li && !li.previousSibling) {
            var parentList = li.parentNode;
            var bk = range.createBookmark();
            if (domUtils.isTagNode(parentList.parentNode, "ol ul")) {
              parentList.parentNode.insertBefore(li, parentList);
              if (domUtils.isEmptyNode(parentList)) {
                domUtils.remove(parentList);
              }
            } else {
              while (li.firstChild) {
                parentList.parentNode.insertBefore(li.firstChild, parentList);
              }

              domUtils.remove(li);
              if (domUtils.isEmptyNode(parentList)) {
                domUtils.remove(parentList);
              }
            }
            range.moveToBookmark(bk).setCursor(false, true);
            me.fireEvent("contentchange");
            me.fireEvent("saveScene");
            domUtils.preventDefault(evt);
            return;
          }
        }
      }
    }
  });

  me.addListener("keyup", function(type, evt) {
    var keyCode = evt.keyCode || evt.which;
    if (keyCode == 8) {
      var rng = me.selection.getRange(),
        list;
      if (
        (list = domUtils.findParentByTagName(
          rng.startContainer,
          ["ol", "ul"],
          true
        ))
      ) {
        adjustList(
          list,
          list.tagName.toLowerCase(),
          getStyle(list) || domUtils.getComputedStyle(list, "list-style-type"),
          true
        );
      }
    }
  });
  //处理tab键
  me.addListener("tabkeydown", function() {
    var range = me.selection.getRange();

    //控制级数
    function checkLevel(li) {
      if (me.options.maxListLevel != -1) {
        var level = li.parentNode,
          levelNum = 0;
        while (/[ou]l/i.test(level.tagName)) {
          levelNum++;
          level = level.parentNode;
        }
        if (levelNum >= me.options.maxListLevel) {
          return true;
        }
      }
    }
    //只以开始为准
    //todo 后续改进
    var li = domUtils.findParentByTagName(range.startContainer, "li", true);
    if (li) {
      var bk;
      if (range.collapsed) {
        if (checkLevel(li)) return true;
        var parentLi = li.parentNode,
          list = me.document.createElement(parentLi.tagName),
          index = utils.indexOf(
            listStyle[list.tagName],
            getStyle(parentLi) ||
              domUtils.getComputedStyle(parentLi, "list-style-type")
          );
        index = index + 1 == listStyle[list.tagName].length ? 0 : index + 1;
        var currentStyle = listStyle[list.tagName][index];
        setListStyle(list, currentStyle);
        if (domUtils.isStartInblock(range)) {
          me.fireEvent("saveScene");
          bk = range.createBookmark();
          parentLi.insertBefore(list, li);
          list.appendChild(li);
          adjustList(list, list.tagName.toLowerCase(), currentStyle);
          me.fireEvent("contentchange");
          range.moveToBookmark(bk).select(true);
          return true;
        }
      } else {
        me.fireEvent("saveScene");
        bk = range.createBookmark();
        for (
          var i = 0, closeList, parents = domUtils.findParents(li), ci;
          (ci = parents[i++]);

        ) {
          if (domUtils.isTagNode(ci, "ol ul")) {
            closeList = ci;
            break;
          }
        }
        var current = li;
        if (bk.end) {
          while (
            current &&
            !(
              domUtils.getPosition(current, bk.end) &
              domUtils.POSITION_FOLLOWING
            )
          ) {
            if (checkLevel(current)) {
              current = domUtils.getNextDomNode(current, false, null, function(
                node
              ) {
                return node !== closeList;
              });
              continue;
            }
            var parentLi = current.parentNode,
              list = me.document.createElement(parentLi.tagName),
              index = utils.indexOf(
                listStyle[list.tagName],
                getStyle(parentLi) ||
                  domUtils.getComputedStyle(parentLi, "list-style-type")
              );
            var currentIndex = index + 1 == listStyle[list.tagName].length
              ? 0
              : index + 1;
            var currentStyle = listStyle[list.tagName][currentIndex];
            setListStyle(list, currentStyle);
            parentLi.insertBefore(list, current);
            while (
              current &&
              !(
                domUtils.getPosition(current, bk.end) &
                domUtils.POSITION_FOLLOWING
              )
            ) {
              li = current.nextSibling;
              list.appendChild(current);
              if (!li || domUtils.isTagNode(li, "ol ul")) {
                if (li) {
                  while ((li = li.firstChild)) {
                    if (li.tagName == "LI") {
                      break;
                    }
                  }
                } else {
                  li = domUtils.getNextDomNode(current, false, null, function(
                    node
                  ) {
                    return node !== closeList;
                  });
                }
                break;
              }
              current = li;
            }
            adjustList(list, list.tagName.toLowerCase(), currentStyle);
            current = li;
          }
        }
        me.fireEvent("contentchange");
        range.moveToBookmark(bk).select();
        return true;
      }
    }
  });
  function getLi(start) {
    while (start && !domUtils.isBody(start)) {
      if (start.nodeName == "TABLE") {
        return null;
      }
      if (start.nodeName == "LI") {
        return start;
      }
      start = start.parentNode;
    }
  }

  /**
     * 有序列表，与“insertunorderedlist”命令互斥
     * @command insertorderedlist
     * @method execCommand
     * @param { String } command 命令字符串
     * @param { String } style 插入的有序列表类型，值为：decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
     * @example
     * ```javascript
     * editor.execCommand( 'insertorderedlist','decimal');
     * ```
     */
  /**
     * 查询当前选区内容是否有序列表
     * @command insertorderedlist
     * @method queryCommandState
     * @param { String } cmd 命令字符串
     * @return { int } 如果当前选区是有序列表返回1，否则返回0
     * @example
     * ```javascript
     * editor.queryCommandState( 'insertorderedlist' );
     * ```
     */
  /**
     * 查询当前选区内容是否有序列表
     * @command insertorderedlist
     * @method queryCommandValue
     * @param { String } cmd 命令字符串
     * @return { String } 返回当前有序列表的类型，值为null或decimal,lower-alpha,lower-roman,upper-alpha,upper-roman,cn,cn1,cn2,num,num1,num2
     * @example
     * ```javascript
     * editor.queryCommandValue( 'insertorderedlist' );
     * ```
     */

  /**
     * 无序列表，与“insertorderedlist”命令互斥
     * @command insertunorderedlist
     * @method execCommand
     * @param { String } command 命令字符串
     * @param { String } style 插入的无序列表类型，值为：circle,disc,square,dash,dot
     * @example
     * ```javascript
     * editor.execCommand( 'insertunorderedlist','circle');
     * ```
     */
  /**
     * 查询当前是否有word文档粘贴进来的图片
     * @command insertunorderedlist
     * @method insertunorderedlist
     * @param { String } command 命令字符串
     * @return { int } 如果当前选区是无序列表返回1，否则返回0
     * @example
     * ```javascript
     * editor.queryCommandState( 'insertunorderedlist' );
     * ```
     */
  /**
     * 查询当前选区内容是否有序列表
     * @command insertunorderedlist
     * @method queryCommandValue
     * @param { String } command 命令字符串
     * @return { String } 返回当前无序列表的类型，值为null或circle,disc,square,dash,dot
     * @example
     * ```javascript
     * editor.queryCommandValue( 'insertunorderedlist' );
     * ```
     */

  me.commands["insertorderedlist"] = me.commands["insertunorderedlist"] = {
    execCommand: function(command, style) {
      if (!style) {
        style = command.toLowerCase() == "insertorderedlist"
          ? "decimal"
          : "disc";
      }
      var me = this,
        range = this.selection.getRange(),
        filterFn = function(node) {
          return node.nodeType == 1
            ? node.tagName.toLowerCase() != "br"
            : !domUtils.isWhitespace(node);
        },
        tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul",
        frag = me.document.createDocumentFragment();
      //去掉是因为会出现选到末尾，导致adjustmentBoundary缩到ol/ul的位置
      //range.shrinkBoundary();//.adjustmentBoundary();
      range.adjustmentBoundary().shrinkBoundary();
      var bko = range.createBookmark(true),
        start = getLi(me.document.getElementById(bko.start)),
        modifyStart = 0,
        end = getLi(me.document.getElementById(bko.end)),
        modifyEnd = 0,
        startParent,
        endParent,
        list,
        tmp;

      if (start || end) {
        start && (startParent = start.parentNode);
        if (!bko.end) {
          end = start;
        }
        end && (endParent = end.parentNode);

        if (startParent === endParent) {
          while (start !== end) {
            tmp = start;
            start = start.nextSibling;
            if (!domUtils.isBlockElm(tmp.firstChild)) {
              var p = me.document.createElement("p");
              while (tmp.firstChild) {
                p.appendChild(tmp.firstChild);
              }
              tmp.appendChild(p);
            }
            frag.appendChild(tmp);
          }
          tmp = me.document.createElement("span");
          startParent.insertBefore(tmp, end);
          if (!domUtils.isBlockElm(end.firstChild)) {
            p = me.document.createElement("p");
            while (end.firstChild) {
              p.appendChild(end.firstChild);
            }
            end.appendChild(p);
          }
          frag.appendChild(end);
          domUtils.breakParent(tmp, startParent);
          if (domUtils.isEmptyNode(tmp.previousSibling)) {
            domUtils.remove(tmp.previousSibling);
          }
          if (domUtils.isEmptyNode(tmp.nextSibling)) {
            domUtils.remove(tmp.nextSibling);
          }
          var nodeStyle =
            getStyle(startParent) ||
            domUtils.getComputedStyle(startParent, "list-style-type") ||
            (command.toLowerCase() == "insertorderedlist" ? "decimal" : "disc");
          if (startParent.tagName.toLowerCase() == tag && nodeStyle == style) {
            for (
              var i = 0, ci, tmpFrag = me.document.createDocumentFragment();
              (ci = frag.firstChild);

            ) {
              if (domUtils.isTagNode(ci, "ol ul")) {
                //                                  删除时，子列表不处理
                //                                  utils.each(domUtils.getElementsByTagName(ci,'li'),function(li){
                //                                        while(li.firstChild){
                //                                            tmpFrag.appendChild(li.firstChild);
                //                                        }
                //
                //                                    });
                tmpFrag.appendChild(ci);
              } else {
                while (ci.firstChild) {
                  tmpFrag.appendChild(ci.firstChild);
                  domUtils.remove(ci);
                }
              }
            }
            tmp.parentNode.insertBefore(tmpFrag, tmp);
          } else {
            list = me.document.createElement(tag);
            setListStyle(list, style);
            list.appendChild(frag);
            tmp.parentNode.insertBefore(list, tmp);
          }

          domUtils.remove(tmp);
          list && adjustList(list, tag, style);
          range.moveToBookmark(bko).select();
          return;
        }
        //开始
        if (start) {
          while (start) {
            tmp = start.nextSibling;
            if (domUtils.isTagNode(start, "ol ul")) {
              frag.appendChild(start);
            } else {
              var tmpfrag = me.document.createDocumentFragment(),
                hasBlock = 0;
              while (start.firstChild) {
                if (domUtils.isBlockElm(start.firstChild)) {
                  hasBlock = 1;
                }
                tmpfrag.appendChild(start.firstChild);
              }
              if (!hasBlock) {
                var tmpP = me.document.createElement("p");
                tmpP.appendChild(tmpfrag);
                frag.appendChild(tmpP);
              } else {
                frag.appendChild(tmpfrag);
              }
              domUtils.remove(start);
            }

            start = tmp;
          }
          startParent.parentNode.insertBefore(frag, startParent.nextSibling);
          if (domUtils.isEmptyNode(startParent)) {
            range.setStartBefore(startParent);
            domUtils.remove(startParent);
          } else {
            range.setStartAfter(startParent);
          }
          modifyStart = 1;
        }

        if (end && domUtils.inDoc(endParent, me.document)) {
          //结束
          start = endParent.firstChild;
          while (start && start !== end) {
            tmp = start.nextSibling;
            if (domUtils.isTagNode(start, "ol ul")) {
              frag.appendChild(start);
            } else {
              tmpfrag = me.document.createDocumentFragment();
              hasBlock = 0;
              while (start.firstChild) {
                if (domUtils.isBlockElm(start.firstChild)) {
                  hasBlock = 1;
                }
                tmpfrag.appendChild(start.firstChild);
              }
              if (!hasBlock) {
                tmpP = me.document.createElement("p");
                tmpP.appendChild(tmpfrag);
                frag.appendChild(tmpP);
              } else {
                frag.appendChild(tmpfrag);
              }
              domUtils.remove(start);
            }
            start = tmp;
          }
          var tmpDiv = domUtils.createElement(me.document, "div", {
            tmpDiv: 1
          });
          domUtils.moveChild(end, tmpDiv);

          frag.appendChild(tmpDiv);
          domUtils.remove(end);
          endParent.parentNode.insertBefore(frag, endParent);
          range.setEndBefore(endParent);
          if (domUtils.isEmptyNode(endParent)) {
            domUtils.remove(endParent);
          }

          modifyEnd = 1;
        }
      }

      if (!modifyStart) {
        range.setStartBefore(me.document.getElementById(bko.start));
      }
      if (bko.end && !modifyEnd) {
        range.setEndAfter(me.document.getElementById(bko.end));
      }
      range.enlarge(true, function(node) {
        return notExchange[node.tagName];
      });

      frag = me.document.createDocumentFragment();

      var bk = range.createBookmark(),
        current = domUtils.getNextDomNode(bk.start, false, filterFn),
        tmpRange = range.cloneRange(),
        tmpNode,
        block = domUtils.isBlockElm;

      while (
        current &&
        current !== bk.end &&
        domUtils.getPosition(current, bk.end) & domUtils.POSITION_PRECEDING
      ) {
        if (current.nodeType == 3 || dtd.li[current.tagName]) {
          if (current.nodeType == 1 && dtd.$list[current.tagName]) {
            while (current.firstChild) {
              frag.appendChild(current.firstChild);
            }
            tmpNode = domUtils.getNextDomNode(current, false, filterFn);
            domUtils.remove(current);
            current = tmpNode;
            continue;
          }
          tmpNode = current;
          tmpRange.setStartBefore(current);

          while (
            current &&
            current !== bk.end &&
            (!block(current) || domUtils.isBookmarkNode(current))
          ) {
            tmpNode = current;
            current = domUtils.getNextDomNode(current, false, null, function(
              node
            ) {
              return !notExchange[node.tagName];
            });
          }

          if (current && block(current)) {
            tmp = domUtils.getNextDomNode(tmpNode, false, filterFn);
            if (tmp && domUtils.isBookmarkNode(tmp)) {
              current = domUtils.getNextDomNode(tmp, false, filterFn);
              tmpNode = tmp;
            }
          }
          tmpRange.setEndAfter(tmpNode);

          current = domUtils.getNextDomNode(tmpNode, false, filterFn);

          var li = range.document.createElement("li");

          li.appendChild(tmpRange.extractContents());
          if (domUtils.isEmptyNode(li)) {
            var tmpNode = range.document.createElement("p");
            while (li.firstChild) {
              tmpNode.appendChild(li.firstChild);
            }
            li.appendChild(tmpNode);
          }
          frag.appendChild(li);
        } else {
          current = domUtils.getNextDomNode(current, true, filterFn);
        }
      }
      range.moveToBookmark(bk).collapse(true);
      list = me.document.createElement(tag);
      setListStyle(list, style);
      list.appendChild(frag);
      range.insertNode(list);
      //当前list上下看能否合并
      adjustList(list, tag, style);
      //去掉冗余的tmpDiv
      for (
        var i = 0, ci, tmpDivs = domUtils.getElementsByTagName(list, "div");
        (ci = tmpDivs[i++]);

      ) {
        if (ci.getAttribute("tmpDiv")) {
          domUtils.remove(ci, true);
        }
      }
      range.moveToBookmark(bko).select();
    },
    queryCommandState: function(command) {
      var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
      var path = this.selection.getStartElementPath();
      for (var i = 0, ci; (ci = path[i++]); ) {
        if (ci.nodeName == "TABLE") {
          return 0;
        }
        if (tag == ci.nodeName.toLowerCase()) {
          return 1;
        }
      }
      return 0;
    },
    queryCommandValue: function(command) {
      var tag = command.toLowerCase() == "insertorderedlist" ? "ol" : "ul";
      var path = this.selection.getStartElementPath(),
        node;
      for (var i = 0, ci; (ci = path[i++]); ) {
        if (ci.nodeName == "TABLE") {
          node = null;
          break;
        }
        if (tag == ci.nodeName.toLowerCase()) {
          node = ci;
          break;
        }
      }
      return node
        ? getStyle(node) || domUtils.getComputedStyle(node, "list-style-type")
        : null;
    }
  };
};
